using System;
using System.Diagnostics;
using System.IO;

using octalforty.Chinchillin.Shared.Deployment;
using octalforty.Chinchillin.Shared.Deployment.Metadata;
using octalforty.Wizardby.Core.Migration.Impl;
using octalforty.Wizardby.Db.SqlServer2000;

namespace octalforty.Chinchillin.Actions.Db
{
    [Action(Name, RollbackAction = "db:downgrade-database")]
    public class UpgradeDatabaseAction : ActionBase
    {
        #region Private Constants
        private const string Name = "upgrade-database";

        private static readonly ActionInfo actionInfo = new ActionInfo {
            Name = Name,
            Description = Resources.Db.BackupDatabaseAction_Description,
            Arguments = new[] {
                new ActionArgumentInfo("database", ActionArgumentType.Uri) { Description = Resources.Db.DatabaseAction_DatabaseArgumentDescription },
                new ActionArgumentInfo("mdl-location", ActionArgumentType.Uri) { Description = Resources.Db.UpgradeDatabaseAction_MdlLocationArgumentDescription }, 
                }
            };
        #endregion

        public IDbPlatformRegistry DbPlatformRegistry
        { get; set; }

        public UpgradeDatabaseAction() :
            base(actionInfo)
        {
        }

        public override void Execute(IActionExecutionContext executionContext)
        {
            try
            {
                var database = (Uri)executionContext.Arguments["database"];
                var mdlLocation = ((Uri)executionContext.Arguments["mdl-location"]).AbsolutePath;

                var dbPlatform = DbPlatformRegistry.ResolveDbPlatform(database.Scheme);
                var connectionString = dbPlatform.GetConnectionInfo(database).ToString();

                TracingManager.TraceEvent(executionContext, TraceEventType.Information, 0, 
                    string.Format("Upgrading Database for platform '{0}' with MDL from '{1}' using connection string '{2}'", 
                    database.Scheme, mdlLocation, connectionString));

                using(var mdlStream = new StreamReader(mdlLocation))
                {
                    var server2008Platform = new Wizardby.Db.SqlServer2008.SqlServer2008Platform();
                    var dbCommandExecutionStrategy = new DbCommandExecutionStrategy();

                    var migrationService = new MigrationService(server2008Platform, 
                        new DbMigrationVersionInfoManager(server2008Platform, dbCommandExecutionStrategy, "SchemaInfo"),
                        new DbMigrationScriptExecutive(dbCommandExecutionStrategy), new FileSystemNativeSqlResourceProvider(Path.GetDirectoryName(mdlLocation)));

                    
                    migrationService.Migrate(connectionString,
                        null, mdlStream);
                } // using
            } // try
            catch(Exception e)
            {
                TracingManager.TraceEvent(executionContext, TraceEventType.Error, 0, e.ToString());
                throw;
            } // catch
        }
    }
}